package hn.cch.spring.core;

import hn.cch.spring.core.annotation.component.BeanInterface;
import hn.cch.spring.core.bean.BeanComponent;
import hn.cch.spring.core.bean.BeanConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.core.env.StandardEnvironment;

import java.util.Objects;

public class BeanFactoryDemo {

    private static final Logger logger = LoggerFactory.getLogger(BeanFactoryDemo.class);


    /**
     * BeanFactory添加BeanPostProcessor
     */
    public static void main(String[] args) {
        // bean工厂
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean定义
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
            .genericBeanDefinition(BeanConfiguration.class).setScope("singleton").getBeanDefinition();
        // bean工厂注册bean定义
        beanFactory.registerBeanDefinition("beanDefinition", beanDefinition);

        // 注册注解配置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // 后置处理器
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()
            .forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));

        // 根据依赖顺序添加后置处理器
        beanFactory.getBeansOfType(BeanPostProcessor.class).values()
            .stream()
            .sorted(Objects.requireNonNull(beanFactory.getDependencyComparator()))
            .forEach(beanFactory::addBeanPostProcessor);

        beanFactory.addEmbeddedValueResolver(new StandardEnvironment()::resolvePlaceholders); // ${}

        for (String name : beanFactory.getBeanDefinitionNames()) {
            logger.info(name);
        }

        beanFactory.preInstantiateSingletons(); // 实例化单例
        BeanComponent beanComponent = beanFactory.getBean(BeanComponent.class);
        BeanInterface beanInterface = beanComponent.getBeanInterface();
        logger.info(beanInterface.getClass().toString());
    }

}
